package product

import (
	"context"

	"mall/common/ctxdatax"
	"mall/common/globalkey"
	"mall/common/resultx"
	"mall/service/backend/common/utils/pointy"
	"mall/service/forum/api/internal/logic/util"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/product/rpc/productclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetPackageByIdLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewGetPackageByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPackageByIdLogic {
	return &GetPackageByIdLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetPackageByIdLogic) GetPackageById(req *types.ProductIdReq) (resp *types.PackageInfo, err error) {
	if req.Id == nil || *req.Id == 0 {
		return nil, resultx.NewErrCode(resultx.PRODUCT_PACKAGE_ID_REQUIRED)
	}

	userId := ctxdatax.GetUserId(l.ctx)
	if userId == 0 {
		return nil, resultx.NewErrCode(resultx.TOKEN_EXPIRE_ERROR)
	}

	var preload string = "product:Id,Title,Slug,Excerpt,Status"
	var eagerLoad string = "product:productMedia,productAttribute,productVariation,productVariationMeta"
	preload += ";productMedia:Id,Uid,Url,Thumbnail,Order"
	preload += ";productAttribute:Id,IsSku,Name,Slug,HasImage"
	preload += ";productVariation:Id,GemPrice,RetailPrice,CounterPrice"
	preload += ";productVariationMeta:mediaId,mediaUrl,sku,skuKey"
	var platformId uint32 = globalkey.ThirdPartyPlatformWechatMini

	var searchLogId *uint64
	if req.SearchId != nil && *req.SearchId > 0 {
		searchLogId = pointy.GetPointer(uint64(*req.SearchId))
	}

	res, err := l.svcCtx.ProductRpc.GetProductById(l.ctx, &productclient.BaseIdReq{
		Id:          req.Id,
		Preload:     pointy.GetPointer(preload),
		EagerLoad:   pointy.GetPointer(eagerLoad),
		VisitorId:   pointy.GetPointer(userId),
		PlatformId:  pointy.GetPointer(platformId),
		SearchLogId: searchLogId,
	})
	if err != nil {
		return nil, err
	}

	if res == nil || res.Id == nil || *res.Id == 0 {
		return nil, resultx.NewErrCode(resultx.PRODUCT_PACKAGE_ID_INVALID)
	}

	var photos []*types.MediaInfo
	if len(res.Media) > 0 {
		for _, v := range res.Media {
			var url string
			if v.Url != nil && len(*v.Url) > 0 {
				url = *v.Url
			}
			if len(url) == 0 && v.Uri != nil && len(*v.Uri) > 0 {
				url = *v.Uri
			}
			var thumbnail *bool
			if v.Thumbnail != nil {
				thumbnail = pointy.GetPointer(*v.Thumbnail > 0)
			}
			photos = append(photos, &types.MediaInfo{
				Uid:       v.Uid,
				Id:        v.Id,
				Url:       pointy.GetPointer(url),
				Thumbnail: thumbnail,
				AltText:   v.AltText,
				MetaData:  v.MetaData,
				Order:     v.Order,
			})
		}
	}

	var skuId *uint64
	var gemPrice *string
	var retailPrice *string
	var counterPrice *string
	if len(res.Skus) > 0 {
		for _, v := range res.Skus {
			skuId = v.Id
			gemPrice = v.GemPrice
			retailPrice = v.RetailPrice
			counterPrice = v.CounterPrice
			break
		}
	}

	var attrs []*types.ProductAttrInfo
	if len(res.Attrs) > 0 {
		for _, v := range res.Attrs {
			if len(v.Options) > 0 {
				var options []*types.ProductAttrOptInfo
				for _, opt := range v.Options {
					options = append(options, &types.ProductAttrOptInfo{
						Id:       opt.Id,
						Label:    opt.Label,
						Slug:     opt.Slug,
						MediaId:  opt.MediaId,
						MediaUrl: opt.MediaUrl,
					})
				}
				var hasMedia *bool
				if v.HasMedia != nil && *v.HasMedia > 0 {
					hasMedia = pointy.GetPointer(true)
				}
				attrs = append(attrs, &types.ProductAttrInfo{
					Id:       v.Id,
					Label:    v.Label,
					Slug:     v.Slug,
					HasMedia: hasMedia,
					Options:  options,
				})
			}
		}
	}

	var specs []*types.ProductAttrInfo
	if len(res.Specs) > 0 {
		for _, v := range res.Specs {
			if len(v.Options) > 0 {
				var options []*types.ProductAttrOptInfo
				for _, opt := range v.Options {
					options = append(options, &types.ProductAttrOptInfo{
						Id:       opt.Id,
						Label:    opt.Label,
						Slug:     opt.Slug,
						MediaId:  opt.MediaId,
						MediaUrl: opt.MediaUrl,
					})
				}
				var hasMedia *bool
				if v.HasMedia != nil && *v.HasMedia > 0 {
					hasMedia = pointy.GetPointer(true)
				}
				specs = append(specs, &types.ProductAttrInfo{
					Id:       v.Id,
					Label:    v.Label,
					Slug:     v.Slug,
					HasMedia: hasMedia,
					Options:  options,
				})
			}
		}
	}

	var statusText *string
	if res.Status != nil {
		statusText = pointy.GetPointer(util.GetStatusText(int32(*res.Status)))
	}

	return &types.PackageInfo{
		Id:           res.Id,
		SkuId:        skuId,
		Title:        res.Title,
		Slug:         res.Slug,
		Excerpt:      res.Excerpt,
		ContentHtml:  res.Content,
		Status:       res.Status,
		StatusText:   statusText,
		Media:        photos,
		Attrs:        attrs,
		Specs:        specs,
		GemPrice:     gemPrice,
		RetailPrice:  retailPrice,
		CounterPrice: counterPrice,
	}, nil
}
